package com.testitems.service.login;

import com.testitems.config.security.JwtTokenUtil;
import com.testitems.config.security.MyUserDetailService;
import com.testitems.config.security.UserInfo;
import com.testitems.controller.login.dto.LoginRequest;
import com.testitems.controller.login.dto.LoginResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

/**
 * <pre>
 *
 * </pre>
 *
 * @author GFH
 * @since 2021-11-20
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private MyUserDetailService userDetailService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    /**
     * 登录认证换取JWT令牌
     */
    @Override
    public LoginResponse login(LoginRequest request) {
        /**
         * 需求登录时需要提示 输入的邮箱不存在
         *      1、所以 先认证 账户是否存在
         *           根据用户名和团队ID查询用户
         *           不存在时 userDetailService.loadUserByUsername抛出 UsernameNotFoundException异常
         *      2、根据请求用户密码
         *          通过springSecurity框架认证与授权 :账户密码匹配
         *          失败抛出 AuthenticationException异常
         *      3、根据用户信息 生成jwtToken token中包含了三部分 声明 用户信息 签证
         */
        final UserInfo userInfo = (UserInfo) userDetailService.loadUserByUsername(request.getUsername());

        userAuthenticationAndAuthorization(request);

        final String token = jwtTokenUtil.generateToken(userInfo);
        final long time = jwtTokenUtil.getExpiredDateFromToken(token).getTime();
        return LoginResponse.builder().jwtToken(token).expiredDate(time).build();
    }

    private void userAuthenticationAndAuthorization(LoginRequest request) {
        final UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword());
        final Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authenticate);
    }


    @Override
    public LoginResponse refreshToken(String token) {
        if (jwtTokenUtil.canRefresh(token)) {
            final String jwtToken = jwtTokenUtil.refreshToken(token);
            final long time = jwtTokenUtil.getExpiredDateFromToken(jwtToken).getTime();
            return LoginResponse.builder().jwtToken(jwtToken).expiredDate(time).build();
        }
        return null;
    }
}
